package statistics;
import events.*;
import traveler.*;
import neighborhood.*;

/**
 * Statistics is a class that is used to hold the statistics for the simulation to access
 * and update.  This class is accessed and updated by the simulation class.
 * 
 * @author Team Switchboard Boxcar (Dan Grissom)
 * 
 */
public class Statistics{

	/**
	*A 4 by 7 array which holds Average objects.  The first index represents the 4 
	*neighborhoods (0-3).  The second index represents the possible routes (0-6).
	*The index used for the neighborhood represents the origin of the route (to show
	*direction).  The index of the routes is interpretted as follows:
	*(0-1) - Represents the road/roads going to the next clockwise neighborhood.
	*(2) - Represents the road (if exists) going to the catacorner neighborhood.
	*(3-4) - Represents the road/roads going to the next counter clockwise neighborhood.
	*(5) - Represents the train track going to the next clockwise neighborhood.
	*(6) - Represents the train track going to the next counter clockwise neighborhood.
	*/
	private Average AverageSpeeds[][]; // Average Speed per route

	/**
	*A 4 by 5 array which holds integers.  The first index represents the 4 
	*neighborhoods (0-3).  The second index represents the possible roads (0-4).
	*The index used for the neighborhood represents the origin of the road (to show
	*direction).  The index of the roads is interpretted as follows:
	*(0-1) - Represents the road/roads going to the next clockwise neighborhood.
	*(2) - Represents the road (if exists) going to the catacorner neighborhood.
	*(3-4) - Represents the road/roads going to the next counter clockwise neighborhood.
	*/
	private int NumAccidents[][]; //Number of accidents that occurred during the simulatoin per route
	
	/**
	* A boolean value which says whether it has rained or not during the simulation
	*/
	private boolean isRain; //Keeps track of whether it rained during the simulatoin or not
	
	/**
	 * The new Statistics Constructor builds the Statistics event with default values.
	 */	
	public Statistics() {
		AverageSpeeds = new Average[4][7];

		//Initialize AverageSpeeds
		for (int i = 0; i < AverageSpeeds.length; i++)
			for (int j = 0; j < AverageSpeeds[i].length; j++)
			{
				AverageSpeeds[i][j] = new Average();
				AverageSpeeds[i][j].RouteDistance = -1;
				AverageSpeeds[i][j].TotalSpeed = 0.0;
				AverageSpeeds[i][j].TotalVehicles = 0;
			}		
		
		
		//Initialize road/track lenghts
		//Roads/Tracks originateing from Upper Class Area (N0)		
		AverageSpeeds[0][0].RouteDistance = 10; 
		AverageSpeeds[0][2].RouteDistance = 30; 
		AverageSpeeds[0][3].RouteDistance = 20; 
		AverageSpeeds[0][5].RouteDistance = 10; 
		AverageSpeeds[0][6].RouteDistance = 20;
		//Roads/Tracks originateing from Industrial Area (N1)
		AverageSpeeds[1][0].RouteDistance = 20; 
		AverageSpeeds[1][1].RouteDistance = 20; 
		AverageSpeeds[1][3].RouteDistance = 10; 
		AverageSpeeds[1][5].RouteDistance = 20; 
		AverageSpeeds[1][6].RouteDistance = 10;
		//Roads/Tracks originateing from DownTown Area (N2)
		AverageSpeeds[2][0].RouteDistance = 10; 
		AverageSpeeds[2][2].RouteDistance = 30; 
		AverageSpeeds[2][3].RouteDistance = 20;
		AverageSpeeds[2][4].RouteDistance = 20; 
		AverageSpeeds[2][5].RouteDistance = 10; 
		AverageSpeeds[2][6].RouteDistance = 20;
		//Roads/Tracks originateing from Lower Class Area (N3)
		AverageSpeeds[3][0].RouteDistance = 20; 
		AverageSpeeds[3][3].RouteDistance = 10;
		AverageSpeeds[3][5].RouteDistance = 20; 
		AverageSpeeds[3][6].RouteDistance = 10;
		
		//Initialize NumAccidents Array to 0
		NumAccidents = new int[4][5];
		
		for (int i = 0; i < NumAccidents.length; i++)
			for (int j = 0; j < NumAccidents[i].length; j++)
					NumAccidents[i][j] = 0;
		
		isRain = false;
	}
	
	/**
	 * SetAccidents updates the accident count for each road.
	 * 
	 * @param NeighIndex
	 * 			Neighborhood index for origin neighborhood.
	 * @param RoadIndex
	 * 			Road index for road that accident occured on.
	 */
	public void SetAccidents(int NeighIndex, int RoadIndex)
	{	NumAccidents[NeighIndex][RoadIndex]++;	}
	
	/**
	 * SetRain saves that it did rain during the simulation.
	 */
	public void SetRain()
	{	isRain = true;	}
	
	/**
	 * SetStats updates the stats for average speed (for road/track) and total cars.
	 * 
	 * @param NeighIndex
	 * 			Index of origin neighborhood.
	 * @param RouteIndex
	 * 			Index of the road thats stats are being updated.
	 * @param TravelingTime
	 * 			Traveling time (in minutes) that car/train traveled on road/track.
	 * @param isCar
	 * 			True if event was a Car_Arrival, False if event was a Train_Arrival.
	 * 
	 * @return True if members were updated successfully.  False if divide by zero error.  
	 */
	public boolean SetStats(int NeighIndex, int RouteIndex, int TravelingTime, boolean isCar) 
	{			
		double TempSpeed = 0.0;
		double TempDist = 0.0;
		
		if (TravelingTime == 0)//divide by zero, ignore data
			return false;
		
		if (isCar)//Car_Arrival
		{
			TempDist = AverageSpeeds[NeighIndex][RouteIndex].RouteDistance;
			TempSpeed = TempDist/TravelingTime*60;//TravelingTime is in minutes
			AverageSpeeds[NeighIndex][RouteIndex].TotalSpeed += TempSpeed;
			AverageSpeeds[NeighIndex][RouteIndex].TotalVehicles ++;
			
		}
		else//Train_Arrival
		{
			TempDist = AverageSpeeds[NeighIndex][RouteIndex].RouteDistance;
			TempSpeed = TempDist/TravelingTime*60;//TravelingTime is in minutes
			AverageSpeeds[NeighIndex][RouteIndex].TotalSpeed += TempSpeed;
			AverageSpeeds[NeighIndex][RouteIndex].TotalVehicles ++;
		}
		
		return true;
	}
	
	/**
	 * GetAverageSpeedPerRoute returns the average speed per route (including waiting time).
	 * 
	 * @param NeighIndex 
	 * 			Integer (0-3) that represents the origin neighborhood.
	 * @param RouteIndex 
	 * 			Integer (0-6) that represents the route of the origin neighborhood.
	 * @return This function returns the AverageSpeed (TotalSpeed/TotalCars) for
	 * 			a specific route.
	 */
	public double GetAverageSpeedPerRoute(int NeighIndex, int RouteIndex) 
	{
		if (AverageSpeeds[NeighIndex][RouteIndex].TotalVehicles == 0)
			return 0.0;
		else
			return ((AverageSpeeds[NeighIndex][RouteIndex].TotalSpeed)
					/ (AverageSpeeds[NeighIndex][RouteIndex].TotalVehicles));
	}
	
	
	/**
	 * GetAverageTravelTimePerRoute returns the average trip time per route in minutes.
	 * 
	 * @param NeighIndex 
	 * 			Integer (0-3) that represents the origin neighborhood.
	 * @param RouteIndex 
	 * 			Integer (0-6) that represents the route of the origin neighborhood.
	 * @return This function returns the AverageSpeed (TotalSpeed/TotalCars) for
	 * 			a specific route.
	 */
	public double GetAverageTravelTimePerRoute(int NeighIndex, int RouteIndex) 
	{
		if (AverageSpeeds[NeighIndex][RouteIndex].TotalVehicles == 0)
			return 0.0;
		else
			return AverageSpeeds[NeighIndex][RouteIndex].RouteDistance * 60
					/ ((AverageSpeeds[NeighIndex][RouteIndex].TotalSpeed)
					/ (AverageSpeeds[NeighIndex][RouteIndex].TotalVehicles));
	}
	/**
	 * GetVehiclesPerRoute returns the total number of vehicles that traveled a route.
	 * 
	 * @param NeighIndex
	 * 			Integer (0-3) that represents the origin neighborhood.
	 * @param RouteIndex 
	 * 			Integer (0-6) that represents the route of the origin neighborhood.
	 * @return This function returns TotalVehicles.
	 */
	public int GetVehiclesPerRoute(int NeighIndex, int RouteIndex) 
	{	return AverageSpeeds[NeighIndex][RouteIndex].TotalVehicles;	}
	
	/**
	 * GetNumAccidentsPerRoad returns the number of accidents that occured.
	 * 
	 * @param NeighIndex
	 * 			Integer (0-3) that represents the origin neighborhood.
	 * @param RoadIndex
	 * 			Integer (0-4) that represents the road of the origin neighborhood.
	 * @return This function returns NumAccidents.
	 */
	public int GetNumAccidentsPerRoad(int NeighIndex, int RoadIndex) 
	{	return NumAccidents[NeighIndex][RoadIndex];	}
	
	/**
	 * GetTotalNumAccidents returns the toal number of accidents that occured in the simulation.
	 * 
	 * @return This function returns the sum of all accidents.
	 */
	public int GetTotalNumAccidents() 
	{	
		int totalNum = 0;
		
		for (int i = 0; i < 4; i++)
		{
			for (int j = 0; j < 5; j++)
			{
				totalNum += NumAccidents[i][j];
			}
		}
		return totalNum;
	}

	/**
	 * GetRainHistory returns whether it rained or not.
	 * 
	 * @return This function returns isRain.
	 */
	public boolean GetRainHistory() 
	{	return isRain;	}
	
	/**
	 * GetAvgVehiclesPerHour returns the average number of cars/trains 
	 * that traversed a certain route per hour.
	 * 
	 * @param NeighIndex
	 * 			Integer (0-3) that represents the origin neighborhood.
	 * @param RouteIndex 
	 * 			Integer (0-6) that represents the route of the origin neighborhood.
	 * @param SimMins
	 * 			The total simulation minutes of the simulation. 
	 * 
	 * @return This function returns Vehicles/Hour/Route.
	 */
	public double GetAvgVehiclesPerHour(int NeighIndex, int RouteIndex, int SimMins) 
	{	
		if (SimMins == 0)
			return 0.0;
		else
			return ((AverageSpeeds[NeighIndex][RouteIndex].TotalVehicles)/(SimMins/60.0));
	}
}